package lt.inkredibl.iit;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import javax.imageio.ImageIO;
import javax.swing.JComponent;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;

@SuppressWarnings("serial")
public class ImgComponent
	extends JComponent
{
	private BufferedImage _img;
	private ZoomTransformer _zt = new ZoomTransformer(1);
	private Contour _contour = new Contour();
	private File _file;
	private List<Drawable> _drawables = new ArrayList<Drawable>();
	private JScrollPane _scroll;
	private ObsDragPoint _obsDrag;
	private ObsAddPoints _obsAdd;
	
	public ImgComponent()
	{
		_obsDrag = new ObsDragPoint(_contour, _zt);
		_obsAdd = new ObsAddPoints(_contour, _zt, _obsDrag);
		_obsDrag.setConflicting(_obsAdd);
		_obsAdd.install(this);
	}

	public void pickCorners()
	{
		_obsAdd.pickCorners();
	}
	
	public void cancelPickCorners()
	{
		_obsAdd.cancelPickCorners();
	}
	
	public boolean isStateReady()
	{
		return _file != null;
	}
	
	public Properties getState()
	{
		Properties p = _contour.getState();
		p.put("file", _file.toString());
		return p;
	}
	
	public void setState(Properties p)
	{
		try
		{
			setImgFile(new File(p.get("file").toString()));
			_contour.setState(p);
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}

	public void setImgFile(File f) throws IOException
	{
		_file = f;
		_img = ImageIO.read(f);
		updateSize();
		//System.out.println(getWidth()+"x"+getHeight());
	}

	private void updateSize()
	{
		if (_img != null)
		{
			super.setSize(_zt.ic2uiSize(_img.getWidth()), _zt.ic2uiSize(_img.getHeight()));
			setPreferredSize(getSize());
			repaint();
		}
	}
	
	@Override
	public void setSize(Dimension d)
	{
		if (_img == null) super.setSize(d);
	}
	
	public void setZoom(int zoom)
	{
		final int vx = _scroll.getHorizontalScrollBar().getValue();
		final int mx = _scroll.getHorizontalScrollBar().getMaximum();
		final int vy = _scroll.getVerticalScrollBar().getValue();
		final int my = _scroll.getVerticalScrollBar().getMaximum();
		_zt.setZoom(zoom == 0 ? 1 : zoom);
		updateSize();
		SwingUtilities.invokeLater(new Runnable(){
			public void run()
			{
				int nmx = _scroll.getHorizontalScrollBar().getMaximum();
				int nmy = _scroll.getVerticalScrollBar().getMaximum();
				int nvx = nmx * vx / mx;
				int nvy = nmy * vy / my;
				_scroll.getHorizontalScrollBar().setValue(nvx);
				_scroll.getVerticalScrollBar().setValue(nvy);
			}
		});
	}

	@Override
	protected void paintComponent(Graphics g)
	{
		//super.paintComponent(g);
		if (_img != null)
		{
			Image img = _img;
			Rectangle vb = g.getClipBounds();
			Rectangle ib = new Rectangle();
			Rectangle sb = new Rectangle();
			
			ib.x = (int)_zt.ui2ic(vb.x);
			ib.y = (int)_zt.ui2ic(vb.y);
			ib.width = (int)_zt.ui2ic(vb.width);
			ib.height = (int)_zt.ui2ic(vb.height);
			fitToImg(ib);
			
			if (ib.width > 0 && ib.height > 0)
			{
				sb.x = (int)_zt.ic2ui(ib.x);
				sb.y = (int)_zt.ic2ui(ib.y);
				sb.width = _zt.ic2uiSize(ib.width);
				sb.height = _zt.ic2uiSize(ib.height);
				
				if (_zt.getZoom() > 1)
				{
					img = _img.getSubimage(ib.x, ib.y, ib.width, ib.height).getScaledInstance(sb.width, sb.height, Image.SCALE_REPLICATE);
				}
				else if (_zt.getZoom() < -1)
				{
					img = _img.getSubimage(ib.x, ib.y, ib.width, ib.height).getScaledInstance(sb.width, sb.height, Image.SCALE_FAST);
				}
				else
				{
					sb.x = 0;
					sb.y = 0;
				}
				g.drawImage(img, sb.x, sb.y, null);
			}
		}
		Grapher grapher = new Grapher(g, _zt);
		_contour.paint(grapher);
		g.setColor(Color.GREEN);
		for (Drawable d: _drawables)
		{
			d.draw(grapher);
		}
	}

	private void fitToImg(Rectangle ib)
	{
		int x1 = ib.x;
		int y1 = ib.y;
		int x2 = ib.x + ib.width;
		int y2 = ib.y + ib.height;
		int w = _img.getWidth();
		int h = _img.getHeight();
		
		if (x1 > w)
		{
			x1 = w;
		}
		if (x2 > w)
		{
			x2 = w;
		}
		if (y1 > h)
		{
			y1 = h;
		}
		if (y2 > h)
		{
			y2 = h;
		}
		
		if (x1 < 0)
		{
			x1 = 0;
		}
		if (y1 < 0)
		{
			y1 = 0;
		}
		if (x2 < 0)
		{
			x2 = 0;
		}
		if (y2 < 0)
		{
			y2 = 0;
		}
		
		ib.x = x1;
		ib.y = y1;
		ib.width = x2 - x1;
		ib.height = y2 - y1;
	}
	
	public Tetragon getQuadragon()
	{
		return _contour.getTetragon();
	}

	public void addDrawable(Drawable d)
	{
		_drawables.add(d);
	}

	public void clearDrawables()
	{
		_drawables.clear();
	}

	public void clearCorners()
	{
		_contour.invalidateCorners();
		cancelPickCorners();
		repaint();
	}

	public Color getImagePixel(int x, int y)
    {
	    return new Color(_img.getRGB(x, y));
    }

	public void autoCorners()
	{
		clearCorners();
		_contour.findCorners();
		repaint();
	}

	public void clearContour()
	{
		_contour.clear();
		repaint();
	}

	public Component makeScroll()
	{
		return _scroll = new JScrollPane(this);
	}
	
}
